﻿using GMap.NET;
using GMap.NET.Internals;
using GMap.NET.MapProviders;
using GMap.NET.WindowsForms;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Vishcious.ArcGIS.SLContrib;

namespace TilesDownloader
{
    public partial class MainForm : Form
    {
        public readonly GMapOverlay _polygons = new GMapOverlay("polygons");

        public MainForm()
        {
            InitializeComponent();

            if (!GMapControl.IsDesignerHosted)
            {
                // add your custom map db provider
                //GMap.NET.CacheProviders.MySQLPureImageCache ch = new GMap.NET.CacheProviders.MySQLPureImageCache();
                //ch.ConnectionString = @"server=sql2008;User Id=trolis;Persist Security Info=True;database=gmapnetcache;password=trolis;";
                //MainMap.Manager.SecondaryCache = ch;

                // config map 39.915, 116.404
                // 24.3094574737, 109.441029377
                // 13.595008333333334, 20.0065
                // 15.298430555555555, 19.42955
                MainMap.ShowTileGridLines = true;
                GMapProviders.GoogleSatelliteMap.TryCorrectVersion = false;
                MainMap.MapProvider = GMapProviders.BaiduMap;                       // 默认地图
                MainMap.Position = new PointLatLng(39.915, 116.404);                // 地图中心点(北京)GPS坐标
                MainMap.MinZoom = GMapProviders.BaiduMap.MinZoom;                   // 地图最小比例
                MainMap.MaxZoom = GMapProviders.BaiduMap.MaxZoom ?? 24;             // 地图最大比例
                MainMap.Zoom = 18;                                                  // 当前缩放等级
                MainMap.DragButton = MouseButtons.Left;                             // 鼠标平移键

                MainMap.MouseMove += MainMap_MouseMove;


                MainMap.Overlays.Add(_polygons);

                GSize size = GMapProviders.GoogleSatelliteMap.Projection.GetTileMatrixMaxXY(0);


                //12178959.70,2773898.00
                //MainMap.FromLocalToLatLng

                //MainMap.Core.p..Position = new PointLatLng(27.7383440, 121.7954890);
                //MainMap.Zoom = 18;

                //CoorExtent(GMapProviders.GoogleSatelliteMap, 6, 109.29783, 24.44277, 109.63463, 24.22818);
                //CoorExtent(GMapProviders.BaiduMap, 1, -180, 75, 180, -75);
                //MakeXML(GMapProviders.GoogleSatelliteMap, 18);

                
                

            }

            InitMaps();
        }
        /// <summary>
        /// 生成瓦片的XML
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="zoom"></param>
        private void MakeXML(GMapProvider provider, int zoom)
        {
            long y = 28852992;
            long x = 53929216;

            PointLatLng p1 = provider.Projection.FromPixelToLatLng(new GPoint(x, y), 18);
            PointLatLng p2 = provider.Projection.FromPixelToLatLng(new GPoint(x + 256, y + 256), 18);
        }

        /// <summary>
        /// 计算坐标范围
        /// </summary>
        /// <param name="provider">地图</param>
        /// <param name="zoom">缩放级别</param>
        /// <param name="left_lng">左上角经度</param>
        /// <param name="top_lat">左上角维度</param>
        /// <param name="right_lng">右下角经度</param>
        /// <param name="bottom_lat">右下角维度</param>
        private void CoorExtent(GMapProvider provider, int zoom, double left_lng, double top_lat, double right_lng, double bottom_lat)
        {
            //109.63463,24.44277,109.29783,24.22818
            GPoint left_top = provider.Projection.FromPixelToTileXY(provider.Projection.FromLatLngToPixel(top_lat, left_lng, zoom));
            GPoint right_bottom = provider.Projection.FromPixelToTileXY(provider.Projection.FromLatLngToPixel(bottom_lat, right_lng, zoom));

            long xmin = left_top.X;
            long xmax = right_bottom.X;
            long ymax = right_bottom.Y;
            long ymin = left_top.Y;

            long xx = xmax - xmin;
            long yy = ymax - ymin;
            long total = (xx + 1) * (yy + 1);

            string text = string.Format("minX = {0}\nmaxX = {1}\nminY = {2}\nmaxY = {3}\nzoom = {4}\n", xmin, xmax, ymin, ymax, zoom);

            GPoint pp = provider.Projection.FromLatLngToPixel(24.3094574737, 109.441029377, 19);
            //List<GPoint> points = provider.Projection.GetAreaTileList(RectLatLng.FromLTRB(left_lng, top_lat, right_lng, bottom_lat), zoom, 0);

            //
            // tfw 格式
            // A 【X方向上的象素分辨素】距离/像素
            // D 【X方向的旋转系数】
            // B 【Y方向的旋转系数】
            // E 【Y方向上的象素分辨率】距离/像素
            // C 【栅格地图左上角象素中心X坐标】
            // F 【栅格地图左上角象素中心Y坐标】

            // 坐标系采用WEB墨卡托
            GPoint lt = provider.Projection.FromTileXYToPixel(left_top);                                            // 左上角像素坐标
            GPoint rb = provider.Projection.FromTileXYToPixel(new GPoint(right_bottom.X + 1, right_bottom.Y + 1));  // 右下角像素坐标
            PointLatLng lt_gps = provider.Projection.FromPixelToLatLng(lt, zoom);                                   // 左上角GPS坐标
            PointLatLng rb_gps = provider.Projection.FromPixelToLatLng(rb, zoom);                                   // 右下角GPS坐标
            // 
            double pixWidth = rb.X - lt.X;      // 总像素宽度
            double pixHeigh = rb.Y - lt.Y;      // 总像素高度
            GSize fullsize = provider.Projection.GetTileMatrixSizePixel(zoom);  // 当前等级瓦片总像素
            // 墨卡托取值范围 [-20037508.3427892,20037508.3427892] 总数:40075016.6855784
            // 求图片左上角和右下角坐标
            double pixLT_X = ((double)lt.X / fullsize.Width) * 40075016.6855784 - 20037508.3427892;
            double pixLT_Y = 20037508.3427892 - ((double)lt.Y / fullsize.Height) * 40075016.6855784;
            double pixRB_X = ((double)rb.X / fullsize.Width) * 40075016.6855784 - 20037508.3427892;
            double pixRB_Y = 20037508.3427892 - ((double)rb.Y / fullsize.Height) * 40075016.6855784;
            //
            double disX = pixRB_X - pixLT_X;        // 实际X距离(m)
            double disY = pixRB_Y - pixLT_Y;        // 实际Y距离(m)


            double pixX = disX / pixWidth;      // X轴像素分辨率
            double pixY = disY / pixHeigh;      // Y轴像素分辨率
            double roX = 0;                     // X方向旋转
            double roY = 0;                     // Y方向旋转
            double offsetX = pixLT_X;
            double offsetY = pixLT_Y;

            text += string.Format("'''\n{0:0.00000000000}\n{1}\n{2}\n{3:0.00000000000}\n{4:0.00000000000}\n{5:0.00000000000}\n'''", pixX, 0, 0, pixY, offsetX, offsetY);

            string coor = string.Format(
                    "\"top_lat\": {0:0.0000000000},\r\n" +
                    "\"left_lng\": {1:0.0000000000},\r\n" +
                    "\"bottom_lat\": {2:0.0000000000},\r\n" +
                    "\"right_lng\": {3:0.0000000000},\r\n",
                    top_lat, left_lng, bottom_lat, right_lng);
        }

        /// <summary>
        /// 
        /// </summary>
        private void InitMaps()
        {
            listViewMaps.Items.Clear();
            foreach (GMapProvider map in GMapProviders.List) {
                ListViewItem item = listViewMaps.Items.Add(map.Name);
                item.ImageIndex = 0;
                item.Tag = map;
            }
        }
        /// <summary>
        /// 
        /// </summary>
        private void MainMap_MouseMove(object sender, MouseEventArgs e)
        {
            PointLatLng pnew = MainMap.FromLocalToLatLng(e.X, e.Y);
            toolStripStatusLabelInfo.Text = string.Format("经度:{0:0.000000} 纬度:{1:0.000000}", pnew.Lng, pnew.Lat);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName"></param>
        private void AddSHPFile(string fileName)
        {
            System.IO.FileInfo fileInfo = new System.IO.FileInfo(fileName);
            ShapeFile shapeReader = new ShapeFile();
            shapeReader.ReadShapes(fileInfo);   // 该方法只读shape
            Collection<ShapeFileRecord> shapeRecords = shapeReader.Records;
            foreach (ShapeFileRecord record in shapeRecords)
            {
                //GMapPolygon polygon = new GMapPolygon(
                List<GMapPolygon> polygons = GetPolygon(record);
                foreach (GMapPolygon polygon in polygons) _polygons.Polygons.Add(polygon);

                
            }
        }
        /// <summary>
        /// 打开SHP文件
        /// </summary>
        private void toolStripButtonAddShp_Click(object sender, EventArgs e)
        {
            OpenFileDialog dialog = new OpenFileDialog();
            dialog.Filter = "SHP文件(*.shp)|*.shp";
            if (dialog.ShowDialog(this) != System.Windows.Forms.DialogResult.OK) return;
            AddSHPFile(dialog.FileName);
        }
        ///// <summary>
        ///// 
        ///// </summary>
        ///// <param name="record"></param>
        ///// <returns></returns>
        //private Graphic ToGraphic(this ShapeFileRecord record)
        //{
        //    if (record == null)
        //        return null;

        //    Graphic graphic = new Graphic();
        //    //add all the attributes to the graphic
        //    foreach (var item in record.Attributes)
        //    {
        //        graphic.Attributes.Add(item.Key, item.Value);
        //    }

        //    //add the geometry to the graphic
        //    switch (record.ShapeType)
        //    {
        //        case (int)ShapeType.NullShape:
        //            break;
        //        case (int)ShapeType.Multipoint:
        //            graphic.Geometry = GetMultiPoint(record);
        //            graphic.Symbol = DEFAULT_MARKER_SYMBOL;
        //            break;
        //        case (int)ShapeType.Point:
        //            graphic.Geometry = GetPoint(record);
        //            graphic.Symbol = DEFAULT_MARKER_SYMBOL;
        //            break;
        //        case (int)ShapeType.Polygon:
        //            graphic.Geometry = GetPolygon(record);
        //            graphic.Symbol = DEFAULT_FILL_SYMBOL;
        //            break;
        //        case (int)ShapeType.PolyLine:
        //            graphic.Geometry = GetPolyline(record);
        //            graphic.Symbol = DEFAULT_LINE_SYMBOL;
        //            break;
        //        default:
        //            break;
        //    }

        //    return graphic;
        //}

        /// <summary>
        /// 
        /// </summary>
        /// <param name="record"></param>
        /// <returns></returns>
        private List<GMapPolygon> GetPolygon(ShapeFileRecord record)
        {
            List<GMapPolygon> polygons = new List<GMapPolygon>();
            for (int i = 0; i < record.NumberOfParts; i++)
            {
                // Determine the starting index and the end index
                // into the points array that defines the figure.
                int start = record.Parts[i];
                int end;
                if (record.NumberOfParts > 1 && i != (record.NumberOfParts - 1)) end = record.Parts[i + 1];
                else end = record.NumberOfPoints;

                List<PointLatLng> points = new List<PointLatLng>();
                // Add line segments to the polyline
                for (int j = start; j < end; j++) {
                    points.Add(new PointLatLng(record.Points[j].Y, record.Points[j].X));
                }
                GMapPolygon polygon = new GMapPolygon(points, string.Format("{0}[{1}]", record.RecordNumber, i));
                polygons.Add(polygon);
            }
            return polygons;
        }
        /// <summary>
        /// 
        /// </summary>
        private void listViewMaps_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listViewMaps.SelectedItems.Count != 1) return;
            ListViewItem item = listViewMaps.SelectedItems[0];
            GMapProvider map = item.Tag as GMapProvider;
            if (map == null) return;
            MainMap.MapProvider = map;
            MainMap.MinZoom = map.MinZoom;              // 地图最小比例
            MainMap.MaxZoom = map.MaxZoom ?? 24;        // 地图最大比例
        }

        private void toolStripButtonDown_Click(object sender, EventArgs e)
        {
            //
            CoorExtent(GMapProviders.GoogleSatelliteMap, 18, MainMap.SelectedArea.Left, MainMap.SelectedArea.Top, MainMap.SelectedArea.Right, MainMap.SelectedArea.Bottom);

        }
    }
}
